AWS SESのバウンスを見やすい形でSlackに通知してみる

AWS SESのバウンスを見やすい形でSlackに通知してみる

Clock Icon2024.12.26

みなさん AWS SES(以下 SES)のバウンス通知の実装はどうしているでしょうか?

メールで通知する場合は比較的簡単に設定できるのですが、Slack への通知は一手間かかります。

今回は Slack でバウンスの通知を整形し、以下のような見やすい形で通知してみます。

スクリーンショット 2024-12-26 午前7.56.15.png

作成した構成

バウンスのイベントを EventBridge で取得し、Chatbot 経由で Slack へ通知します。
バウンスメール.png

入力トランスフォーマーの整形を入れないと、以下のような通知になるのですが、これだと情報が足りません。

スクリーンショット 2024-12-26 午前8.05.13.png

バウンスが発生したことは分かりますが、どの送信元メールなのか、原因は何かなど、調査に必要な情報が欲しくなりますよね。

そのため EventRule 内で必要な情報を取得・整形した上で Slack へ通知する形を取りました。

やってみる

CloudFormation のテンプレートを作成したので、試したい方はこちらをご利用ください。

前提として以下の環境で利用してください。

  • Slack のワークスペース連携済み
  • 検証済みの SES ID が存在している
AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  Prefix:
    Type: String
    Description: Prefix for SES
    Default: ses-bounce

  BounceSlackChannel:
    Type: String

  SlackWorkspace:
    Type: String

Resources:
  SESConfigurationSet:
    Type: "AWS::SES::ConfigurationSet"
    Properties:
      Name: !Sub "${Prefix}-configuration-set"
      SendingOptions:
        SendingEnabled: true

  SESEventDestinationEventBridge:
    Type: "AWS::SES::ConfigurationSetEventDestination"
    Properties:
      ConfigurationSetName: !Ref SESConfigurationSet
      EventDestination:
        Name: !Sub "${Prefix}-destination-eventbridge"
        Enabled: true
        MatchingEventTypes:
          - "bounce"
        EventBridgeDestination:
          EventBusArn: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default"

  SESBounceTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: "SES Bounce Topic"
      TopicName: !Sub "${Prefix}-ses-bounce-topic"

  SESBounceTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      Topics:
        - !Ref SESBounceTopic
      PolicyDocument:
        Version: "2008-10-17"
        Statement:
          - Sid: "DefaultSNSPolicy"
            Effect: Allow
            Principal:
              AWS: "*"
            Action:
              - SNS:GetTopicAttributes
              - SNS:SetTopicAttributes
              - SNS:AddPermission
              - SNS:RemovePermission
              - SNS:DeleteTopic
              - SNS:Subscribe
              - SNS:ListSubscriptionsByTopic
              - SNS:Publish
            Resource: !Ref SESBounceTopic
            Condition:
              StringEquals:
                AWS:SourceOwner: !Ref AWS::AccountId
          - Sid: "AllowEventBridgeToPublishToSNS"
            Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: SNS:Publish
            Resource: !Ref SESBounceTopic

  SESBounceEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub "${Prefix}-ses-bounce-rule"
      Description: "Rule to capture SES bounce events and notify via Chatbot"
      State: ENABLED
      EventPattern:
        source:
          - aws.ses
        detail-type:
          - "Email Bounced"
      Targets:
        - Arn: !Ref SESBounceTopic
          Id: "ses-bounce-topic"
          InputTransformer:
            InputPathsMap:
              bounceType: "$.detail.bounce.bounceType"
              bounceSubType: "$.detail.bounce.bounceSubType"
              emailAddress: "$.detail.bounce.bouncedRecipients[0].emailAddress"
              status: "$.detail.bounce.bouncedRecipients[0].status"
              diagnosticCode: "$.detail.bounce.bouncedRecipients[0].diagnosticCode"
              messageId: "$.detail.mail.messageId"
              source: "$.detail.mail.source"
              timestamp: "$.detail.bounce.timestamp"
              subject: "$.detail.mail.commonHeaders.subject"
            InputTemplate: |
              {
                "version":"1.0",
                "source":"custom",
                "content":{
                  "textType": "client-markdown",
                  "title":"📧 SES バウンスメール検知",
                  "description":"以下のメール送信でバウンスが発生しました\n\n*バウンス情報:*\n• バウンスタイプ: <bounceType>\n• バウンスサブタイプ: <bounceSubType>\n• エラーコード: <status>\n• エラー診断: <diagnosticCode>\n\n*送信情報:*\n• 送信元: <source>\n• 送信先: <emailAddress>\n• 件名: <subject>\n• メッセージID: <messageId>\n• 発生時刻: <timestamp>",
                  "nextSteps":[
                    "バウンスタイプに応じて以下の対応を検討してください:",
                    "- Permanent: 送信先アドレスの無効化や修正",
                    "- Transient: 一時的な問題として監視"
                  ]
                }
              }

  EventBridgeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: ChatbotInvokePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - chatbot:*
                Resource: "*"

  ChatbotSlackBounceChannel:
    Type: AWS::Chatbot::SlackChannelConfiguration
    Properties:
      ConfigurationName: !Sub "${Prefix}-bounce-notification"
      IamRoleArn: !GetAtt ChatbotRole.Arn
      SlackChannelId: !Ref BounceSlackChannel
      SlackWorkspaceId: !Ref SlackWorkspace
      GuardrailPolicies:
        - "arn:aws:iam::aws:policy/ReadOnlyAccess"
      SnsTopicArns:
        - !Ref SESBounceTopic

  ChatbotRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - chatbot.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/ReadOnlyAccess

SESに設定セットを紐づける

CloudFormation で作成した設定セットをバウンス通知を設定したい ID に紐づけます。

スクリーンショット 2024-12-26 午前8.01.15.png

Slackの通知先チャンネルにAWSアプリを招待

プライベートチャンネルには AWS アプリを招待する必要があります。

/invite @aws

もし対象のチャンネルに招待していなければ招待しておきましょう。

バウンスメールの通知確認

準備が整ったので、バウンスメールを発生させて通知が飛ぶか確認してみます。

設定セットを紐づけた ID からテストメールを送信しましょう。シナリオから「バウンス」を選択し、件名と本文は任意のものを入れます。

スクリーンショット 2024-12-26 午前8.13.12.png

これでメールを送信すると、Slack へ通知されるはずです。

スクリーンショット 2024-12-26 午前7.56.15.png

バウンス自体の情報と送信したメールの詳細情報が通知されます。

注意点

SESイベントはデフォルトでは送信されない

SES イベントはデフォルトでは EventRule で取得できません。
https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html

イベントを送信するには、SES の設定セットで「イベントの送信先」を設定しないといけない点に注意してください。今回はテンプレートの中で設定していますが、手動で作成する場合は気をつけましょう。

https://docs.aws.amazon.com/ja_jp/ses/latest/dg/using-configuration-sets.html

フィードバック通知からSlackへの通知はできない

ID 単位で設定できるフィードバック通知ですが、ここの Bounce に SNS トピックを設定して Chatbot 経由での通知はできません。イベント形式が EventBridge 経由とは異なるため Chatbot が未対応だと思われます。
スクリーンショット 2024-12-26 午前10.04.53.png

メールでの通知であればここに設定でも良いですが、Chatbot を使って通知したい場合は設定セットのイベント送信先を利用しましょう。

終わりに

AWS SES のバウンスを見やすい形で Slack に通知してみました。大量のメール通知を行う場合は Slack での確認は難しいですが、少量であれば Slack での運用も可能です。
バウンスの通知だけでなく、詳細情報としてVirtual Deliverability Managerを有効化したり、ログを取得しておくことも重要です。しっかり設定しておきましょう。

メールよりは Slack 上の方が気づきやすく運用しやすいと思いますので、SES を運用する際の一助となれば幸いです。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.